/***********************************************************************//**
 *   \file Instrument.h		\author belot nicolas (karrakis)            *
     define Class Instrument                                               
 *   an interface for managing instrument                                  *
 *//************************************************************************
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
****************************************************************************/

#ifndef INSTRUMENT_H
#define INSTRUMENT_H 1


#include <deque>
#include <string>
#include <map>
//#include constant.h contiendra les constantes necessaires (note => freq, etc)
#include "Sample.h"
#include "Filter.h"
#include "Note.h"
#include "DynArray"
#include "Converter.h"
#include "PlayingEffect.h"
using namespace std;

namespace libtrckr {
class Instrument {
/** \class libtrckr::Instrument
    \brief Interface for Instrument */
public :
	///Constructor
	Instrument();
	///Copy construtor
	Instrument(const Instrument&);
	///Destructor
	virtual ~Instrument();

	//Accessor
	//Information
	/// \return the name of the instrument
	virtual string getName() const =0;
	/// \return the tuning of the instrument
	virtual DynArray<string> getTuning() const=0;//Huh! vector :s
	/// \return Instruments attacks names.
	virtual DynArray<string> getAttacks() const=0;

	//Creation 
	/// set the name of the instrument
	virtual void setName( string )=0;
	/// set the tuning of the instrument
	virtual void setTuning( DynArray<string> )=0;
	/// Append a note in the instrument
	virtual void setNote( string, string,float, short,short=0,short=0)=0;// ça devrais plutot prendre un string filename.
	/** add a filter
	\param f the filter
	\param parent the filter parent
	\return filter index
	*/
	int addFilter( Filter*, int );
	/** add a filter
	\param f the filter
	\param parent the filter parents
	\return filter index
	*/
	int addFilter( Filter*, DynArray<int> );
	/** set a filter
	\param f the filter
	\param index the index of the filter */
	void setFilter( Filter*, int);
	/** remove a filter
	\param index the filter index */
	virtual void removeFilter( int);
	///set Attacks
	virtual void setAttack(DynArray<string> )=0;
	/// \overload
	virtual void setAttack(string** )=0;

	//Function working with the rest of the libs.
	///Play size sample
	virtual Buffer play( uint)=0;//play xsample.
	/// \overload
	virtual Buffer& play(Buffer & )=0;//play xsample.
	/** todo Mettre attack par defaut si l'attaque n'existe pas.*/
	///Append a note in a partitition.
	virtual void addNote(string, Duration::note_duration_t,bool, uint,short=0,short=0,DynArray<PlayingEffect*>* =0)=0 ;// hmmm ça devrais plutot retourner un Buffer charger du sample
	/// \overload
	virtual void addNote(Note, uint,short,short,DynArray<PlayingEffect*>* =0)=0 ;// hmmm ça devrais plutot retourner un Buffer charger du sample
	/// return a filters list...
	DynArray<Filter*> getFiltersList() const;//retournons un tableau ça me parais plus sur :)
	/// not realy sure of what this one does.
	Filter* getFilter() const;//???
	/// Apply the filters of the buffer.
	Buffer& ApplyFilters(Buffer&);
	///did we reach the end of the partition ?
	virtual bool end() const=0;
	/// Some instrument allow us do not silence old note...
	virtual void letRing(bool)=0;
	/// Apply the naturalEffects (like bend...) on the Buffer.
	Buffer& naturalEffects(Buffer&,Sample&,DynArray<PlayingEffect*>*);

	struct INote {
		/** \struct libtrckr::Instrument::INote 
			structure used to memorise note information
		*/
		Note _note;
		double _volume;
		unsigned short _panning;
		string filename;
		float speed;
		short attack;
		DynArray<PlayingEffect*>* playing;
	};

	struct BoucleEffet {
		/** \struct libtrckr::Instrument::BoucleEffet
			something you don't want to hear about ;) */
		DynArray<int> in;
		DynArray<int> out;
		int filtre;

		BoucleEffet();
	};

	struct Thread{
		/** \struct libtrckr::Instrument::Thread
			Thread used to simulate derivation in the Filters Circuit */
		pthread_t tr;
		bool fini;
	};
	///Forget it
	friend void *ApplyFilter(void*);
	private :
		
		deque<Filter*> _filters;
		DynArray<BoucleEffet> _be;
		map<string,Buffer*> buffers;
		map<string,Thread> process;
		DynArray<string> abranches;

};
	///...
	///\todo remove it...
	Buffer &grab(Converter&,Buffer&, Sample&,double);
}
#endif

